package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.WorkOrderPersonEntity;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.WorkOrderFlowNodeTypeEnum;
import com.xbongbong.saas.enums.WorkOrderStageRobTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.WorkOrderFlowNodeModel;
import com.xbongbong.saas.model.WorkOrderFlowUserModel;
import com.xbongbong.saas.service.WorkOrderPersonService;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author haibin.zhang
 * @version v1.0
 * @date 2019/5/5 10:07
 * @since v1.0
 */
@Component
public class WorkOrderListDataPermissionHelp {
    @Resource
    private WorkOrderFlowNodeModel workOrderFlowNodeModel;
    @Resource
    private UserModel userModel;
    @Resource
    private WorkOrderPersonService workOrderPersonService;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private WorkOrderFlowUserModel workOrderFlowUserModel;
    /**
     * 工单列表页数据权限
     * 为节约性能，特将超时逻辑放在此处
     *
     * @param conditionsList
     * @param userVO
     * @param defaultGroup
     * @param listGroupId
     */
    public void listDataPermission(List<ConditionsEntityExt> conditionsList, List<List<ConditionsEntityExt>> shouldConditionList, UserVO userVO, Integer defaultGroup, Long listGroupId){
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        String corpid = userEntity.getCorpid();
        Boolean isBoss = userVO.isMaxDataPermission();
        Boolean isOut = null;
        Iterator<ConditionsEntityExt> iterator = conditionsList.iterator();
        while (iterator.hasNext()){
            ConditionsEntityExt entityExt = iterator.next();
            if (Objects.equals(entityExt.getFieldType(),FieldTypeEnum.WORK_ORDER_TIME_OUT.getType())){
                isOut = Objects.equals(entityExt.getValue().get(0),"0");
                iterator.remove();
                break;
            }
        }
        if (Objects.equals(defaultGroup,1) && !Objects.equals(listGroupId, ListGroupEnum.ALL.getCode().longValue())){
            //默认分组,超时逻辑
            if (Objects.isNull(listGroupId)) {
                listGroupId = 0L;
            }
            ListGroupEnum listGroupEnum = ListGroupEnum.getByCode(listGroupId.intValue());
            switch (listGroupEnum){
                case WORK_ORDER_CREATE_BY_ME:
                case WORK_ORDER_COOPERATE_BY_ME:
                case WORK_ORDER_COPY_BY_ME:
                    workOrderIsOut(isOut,Collections.singletonList(userEntity.getUserId()),conditionsList);
                    break;
                case WORK_ORDER_CREATE_BY_SUB:
                case WORK_ORDER_COOPERATE_BY_SUB:
                    Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_ORDER.getCode(), null);
                    List<String> subUserIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE,true);
                    workOrderIsOut(isOut,subUserIdIn,conditionsList);
                    break;
                case WORK_ORDER_RESPONSE_BY_ME:
                    workOrderNodeIsOut(isOut,corpid,Collections.singletonList(userEntity.getUserId()),conditionsList);
                    break;
                case WORK_ORDER_RESPONSE_BY_SUB:
                    //node超时
                    Integer permission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_ORDER.getCode(), null);
                    subUserIdIn = userModel.getSubIdListByDataPermission(permission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE,true);
                    workOrderNodeIsOut(isOut,corpid,subUserIdIn,conditionsList);
                    break;
                case APPROVAL:
                    listDataBasePermission(conditionsList, shouldConditionList, userEntity, isBoss, isOut);
                    break;
                default:
                    break;
            }
        } else {
            //data超时
            listDataBasePermission(conditionsList, shouldConditionList, userEntity, isBoss, isOut);
        }
    }

    private void listDataBasePermission(List<ConditionsEntityExt> conditionsList, List<List<ConditionsEntityExt>> shouldConditionList, UserEntity userEntity, Boolean isBoss, Boolean isOut) {
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_ORDER.getCode(), null);
        List<String> subUserIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE,false);
        workOrderIsOut(isOut,subUserIdIn, conditionsList);
//            if (!isBoss && !isWorkOrderManager){
        if (!isBoss){
            //低权限查询结构变更
            //低权限聚合一下我和下属负责的
            //创建人
            ConditionsEntityExt createCondition = new ConditionsEntityExt();
            createCondition.setAttr(FieldTypeEnum.CREATORID.getAlias());
            createCondition.setFieldType(FieldTypeEnum.CREATORID.getType());
            createCondition.setSymbol(ConditionEnum.IN.getSymbol());
            createCondition.setValue(new ArrayList<>(subUserIdIn));
            //抄送人
            ConditionsEntityExt copyCondition = new ConditionsEntityExt();
            copyCondition.setAttr(FieldTypeEnum.COPY_USER.getAlias());
            copyCondition.setFieldType(FieldTypeEnum.COPY_USER.getType());
            copyCondition.setSymbol(ConditionEnum.EQUAL.getSymbol());
            copyCondition.setValue(Collections.singletonList(userEntity.getUserId()));
            //协同人
            ConditionsEntityExt teamCondition = new ConditionsEntityExt();
            teamCondition.setAttr(FieldTypeEnum.COUSERID.getAlias());
            teamCondition.setFieldType(FieldTypeEnum.COUSERID.getType());
            teamCondition.setSymbol(ConditionEnum.IN.getSymbol());
            teamCondition.setValue(new ArrayList<>(subUserIdIn));
            //负责人
            ConditionsEntityExt ownerCondition = new ConditionsEntityExt();
            ownerCondition.setAttr(FieldTypeEnum.OWNERID.getAlias());
            ownerCondition.setFieldType(FieldTypeEnum.OWNERID.getType());
            ownerCondition.setSymbol(ConditionEnum.IN.getSymbol());
            ownerCondition.setValue(new ArrayList<>(subUserIdIn));
//                List<Long> workOrderIdIn = workOrderFlowNodeModel.getWorkOrderIdResponsibleByUserIdIn(corpid,subUserIdIn);
//                List<Long> workOrderIdIn = workOrderFlowUserModel.getWorkOrderIdByUserIdIn(corpid, subUserIdIn, 1);
//                ConditionsEntityExt dataIdCondition = new ConditionsEntityExt();
//                dataIdCondition.setAttr(FieldTypeEnum.DATAID.getAlias());
//                dataIdCondition.setFieldType(FieldTypeEnum.DATAID.getType());
//                dataIdCondition.setSymbol(ConditionEnum.IN.getSymbol());
//                dataIdCondition.setValue(new ArrayList<>(workOrderIdIn));
//                //workOrderIdIn工单编号为空时，导致es语句不对，导致list查询出的工单数据不对
//                if (workOrderIdIn.size() > 0) {
//                    shouldConditionList.add(Collections.singletonList(dataIdCondition));
//                }
            shouldConditionList.add(Collections.singletonList(ownerCondition));
            shouldConditionList.add(Collections.singletonList(createCondition));
            shouldConditionList.add(Collections.singletonList(teamCondition));
            shouldConditionList.add(Collections.singletonList(copyCondition));
        }
    }

    /**
     * 抢单列表数据权限
     * @param conditions
     * @param userVO
     * @param depSet
     */
    public void robListDataPermission(List<ConditionsEntityExt> conditions, UserVO userVO, Set<DepartmentVO> depSet) throws XbbException{
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        String corpid = userEntity.getCorpid();
        Boolean isOut = null;
        Iterator<ConditionsEntityExt> iterator = conditions.iterator();
        while (iterator.hasNext()){
            ConditionsEntityExt entityExt = iterator.next();
            if (Objects.equals(entityExt.getFieldType(),FieldTypeEnum.WORK_ORDER_TIME_OUT.getType())){
                isOut = Objects.equals(entityExt.getValue().get(0),"0");
                iterator.remove();
                break;
            }
        }
        //data超时
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.WORK_ORDER.getCode(), null);
        List<String> subUserIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE, false);
        workOrderIsOut(isOut,subUserIdIn,conditions);
        if (Objects.equals(dataPermission, DataPermissionEnum.ALL.getCode())){
            return;
        }
        List<WorkOrderPersonEntity> workOrderPersonEntityList = workOrderPersonService.getPersonListByUser(corpid,userEntity.getUserId());
        Set<String> allTagIdSet = new HashSet<>();
        for (WorkOrderPersonEntity entity : workOrderPersonEntityList){
            List<String> tagIdList = JSONArray.parseArray(entity.getTagId(),String.class);
            allTagIdSet.addAll(tagIdList);
        }
        List<String> allTagIdList = new ArrayList<>(allTagIdSet);
        List<Long> depIdList = new ArrayList<>();
        for (DepartmentVO departmentVO : depSet){
            depIdList.add(departmentVO.getId());
        }
        List<Long> supDepIdList = departmentModel.getSupDepIdList(corpid, depIdList, false);
        // 数据库为string， 转成string索引命中
        List<String> supDepIdStrList = supDepIdList.stream().map(Object::toString).collect(Collectors.toList());
//        List<Long> allDepIdList = departmentModel.getSubDepIdList(corpid,depIdList);
//        List<String> allDeoIdStrList = JSONArray.parseArray(allDepIdList.toString(),String.class);
        List<Long> robWorkOrderIdList = new ArrayList<>();
        if (!allTagIdList.isEmpty()){
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            param.put("nodeType",WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode());
            param.put("robType",WorkOrderStageRobTypeEnum.SERVICE.getCode());
            param.put("robIdIn",allTagIdList);
            List<Long> workOrderIdList = workOrderFlowNodeModel.workOrderIdList(param);
            robWorkOrderIdList.addAll(workOrderIdList);
        }
        if (!supDepIdList.isEmpty()){
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            param.put("nodeType",WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode());
            param.put("robType",WorkOrderStageRobTypeEnum.DEPARTMENT.getCode());
            param.put("robIdIn", supDepIdStrList);
            List<Long> workOrderIdList = workOrderFlowNodeModel.workOrderIdList(param);
            robWorkOrderIdList.addAll(workOrderIdList);
        }
        if (robWorkOrderIdList.isEmpty()){
            robWorkOrderIdList.add(-1L);
        }
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(FieldTypeEnum.DATAID.getAlias());
        conditionsEntityExt.setFieldType(FieldTypeEnum.DATAID.getType());
        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
        conditionsEntityExt.setValue(new ArrayList<>(robWorkOrderIdList));
        conditions.add(conditionsEntityExt);
    }

    /**
     * 工单节点超时
     * @param isOut 是否超时判断
     */
    private void workOrderNodeIsOut(Boolean isOut,String corpid,List<String> userIdIn,List<ConditionsEntityExt> conditionsList) {
        if (Objects.isNull(isOut)){
            return;
        }
        if (userIdIn.isEmpty()) {
            userIdIn.add("-1");
        }
        List<Long> workOrderIdList;
        //超时：进行中当前时间-开始时间超过预计完成时间或耗时超过预计完成时间
        //未超时：未开始或当前时间-开始时间未超过预计完成时间或耗时未超过预计完成时间
        workOrderIdList = workOrderFlowNodeModel.getTimeOutNode(corpid,userIdIn,isOut);
        if (workOrderIdList.isEmpty()){
            workOrderIdList.add(-1L);
        }
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(FieldTypeEnum.DATAID.getAlias());
        conditionsEntityExt.setFieldType(FieldTypeEnum.DATAID.getType());
        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
        conditionsEntityExt.setValue(new ArrayList<>(workOrderIdList));
        conditionsList.add(conditionsEntityExt);
    }

    /**
     * 工单数据超时
     * @param isOut 是否超时判断
     */
    private void workOrderIsOut(Boolean isOut,List<String> userIdIn,List<ConditionsEntityExt> conditionsList) {
        if (Objects.isNull(isOut)){
            return;
        }
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        if (isOut){
            //超时：进行中当前时间-开始时间超过预计完成时间或耗时超过预计完成时间
            conditionsEntityExt.setAttr(FieldTypeEnum.WORK_ORDER_DATA_TIME_OUT.getAlias());
            conditionsEntityExt.setFieldType(FieldTypeEnum.WORK_ORDER_DATA_TIME_OUT.getType());
        }else {
            //未超时：未开始或当前时间-开始时间未超过预计完成时间或耗时未超过预计完成时间
            conditionsEntityExt.setAttr(FieldTypeEnum.WORK_ORDER_DATA_TIME_NOT_OUT.getAlias());
            conditionsEntityExt.setFieldType(FieldTypeEnum.WORK_ORDER_DATA_TIME_NOT_OUT.getType());
        }
        conditionsEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
        conditionsEntityExt.setValue(Collections.singletonList("0"));
        conditionsList.add(conditionsEntityExt);

    }
}
